from game_client import MyBattleshipClient
from game_shared import WATER_CELLS
from player_boat_placement_util import BoatPlaceUtil
import time

class PlayerClient( MyBattleshipClient ):
    def __init__(self, game_id, player_id, server_port):
        MyBattleshipClient.__init__(self)
        self.connect('localhost', server_port)
        self.game_id = game_id
        self.player_id = player_id
        
        self.player_state = 0
        self.game_over = False
        self.last_shot = ( 0,0 )
        self.last_shot_hit = False
        self.shots = []
        self.opponents_last_game_shots = None
        
        self.boat_util = BoatPlaceUtil()
    
    def get_valid_cells(self):
        return WATER_CELLS
        
    def get_shots(self):
        return self.shots
    
    
    def get_opponents_last_game_shots(self):
        return self.opponents_last_game_shots
    
    
    def is_last_shot_hit(self):
        return self.last_shot_hit
    
    def get_last_shot(self):
        return self.last_shot
    
    
    def reinitialize(self):
        """placed at the beginning of loop."""
        raise NotImplementedError
    
    def boat_place_algorithm(self):
        ''' Should return a list of 5 boats. 
            In the format: boats = [ [ length, x_coord, y_coord, orientation ] x 5 ] '''
        raise NotImplementedError
    
    def shoot_algorithm(self):
        ''' Should return a tuple representing coordinate to shoot at. '''
        raise NotImplementedError
    
    def place_all_boats(self, boats):
        for boat in boats:
            self.place_boat( self.game_id, self.player_id, boat[0], boat[1], boat[2], boat[3] )
    
    def win_or_lose(self): 
        outcome = self.did_i_win( self.game_id, self.player_id )
        if outcome:
            print "[Final Result] You won the game! : )"
        else:
            print "[Final Result] You lost the game : ("   
    
    def enter_game_client(self):
        ''' Enter the game before run() '''
        self.enter_game( self.game_id, self.player_id)
        self.player_state = 1

    def w_l_count(self):
        record = self.win_loss_count( self.game_id, self.player_id )
        return "WINS: {0} LOSSES:{1}".format(record[0], record[1])
    
    def reset(self):
        self.player_state = 3
        self.shots = []
        self.opponents_last_game_shots = self.get_opponents_last_game_placement(self.game_id, self.player_id)
        self.boat_util = BoatPlaceUtil()  
    
    def print_stats(self):
        record = self.win_loss_count( self.game_id, self.player_id )
        print "\n[Game Update]"
        print "[Wins]\t\t\t", record[0]
        print "[Losses]\t\t", record[1] 
        print "[Avg. Shots Taken]\t", self.get_avg_shots_taken(self.game_id, self.player_id) 
    
    def run(self, verbose=False,testing=False):
        ''' Sets the player in motion. Should ONLY be called once the player has entered the game by calling enter_game_client()'''
        
        counter = 2
        counter_2 = 1
        
        while not self.game_over:
            
            game_state = self.get_state( self.game_id )
            time.sleep(0.05)
            player_state = self.player_state
            
            counter += 1
            if counter % 2000 == 0 and verbose:
                print "Game in progress........"
            
            if testing:
                print "-------"
                print "[Beginning of Loop]"
                print "Player {0} is in state {1}.".format( self.player_id, player_state )
                print "The game they're in is in state {0}\n".format( game_state )
            
            
            # 1 - Check if other player has entered game, if not, wait.
            if game_state == 1:
                if verbose: print "[Waiting for opponent to enter game]"
            
            # 2 - Check if game has move to state 2, which means opponent is ready for boards.
            elif game_state == 2 and player_state != 2:
                self.reinitialize()
                
                if verbose: print "[Exchanging boards]"
                
                self.player_state = 2 
                boats = self.boat_place_algorithm()
                self.place_all_boats( boats )     
            
            # 3 - Check if game has moved to state 3, which means it's time for battle.
            elif game_state == 3 and player_state != 3:
                x_coord, y_coord = self.shoot_algorithm()
                
                self.shots.append( (x_coord, y_coord) )
                self.last_shot = (x_coord, y_coord)
                
                result = self.shoot( self.game_id, self.player_id, x_coord, y_coord )
                
                if result[0] == 187:
                    counter_2 += 1
                    self.reset()
                    if counter_2 > 1 and counter_2 % 2==0: 
                        self.print_stats()
                    if result[1] == 1: 
                        print "[Invalid Shot] You lost the game due to a shot at {0} an invalid location.".format( (x_coord, y_coord) )
                                
                elif result[0]:
                    self.last_shot_hit = True
                    if verbose: print "[Hit] ({0}, {1})".format( x_coord,y_coord )
                
                else:
                    self.last_shot_hit = False
                    if verbose: print "[Miss] ({0}, {1})".format( x_coord,y_coord )
            
            # 4 - Check if game has ended, if so, break.
            elif game_state == 4:
                self.game_over = True
                self.win_or_lose()
                print "[Final Score]", self.w_l_count()
            
            # 5 - Or else, keep looping.
            else:
                pass
            
            if testing:
                
                print "[End of Loop]"
                print "Player {0} is in state {1}.".format( self.player_id, player_state )
                print "The game their in is in state {0}\n".format( game_state )
                print "-------"
